package jesss.commands;

import com.amazonaws.AmazonClientException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.CopyObjectResult;
import jesss.options.ExtendedGnuParser;
import jesss.options.JesssOptions;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.MissingArgumentException;
import org.apache.commons.cli.Options;

/**
 * User: Lee
 * Date: 8/26/13
 * Time: 10:31 PM
 */
public class CopyObjectCommand<T> extends AbstractJesssCommand {

    private JesssOptions jesssOptions = null;
    private Options options = new Options();
    private String sourceBucketName;
    private String sourceKey;
    private String targetBucketName;
    private String targetKey;

    public CopyObjectCommand(JesssOptions jesssOptions) throws Exception {
        this.jesssOptions = jesssOptions;
        this.setShouldDisplayVerbose(jesssOptions.getShouldDisplayVerbose());
        setOptions();
        try {
            parseArgs(jesssOptions.getArgs());
        } catch (Exception e) {
            printUsage();
            throw e;
        }
    }

    /**
     * Copies an object from one bucket to another.
     *
     * @return The CopyObjectResult contains information about the object that was copied.
     */
    @Override
    public CommandResult<CopyObjectResult> executeCommand() {
        displayMessage("Calling copyObject...");
        CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceKey, targetBucketName, targetKey);
        CommandResult<CopyObjectResult> commandResult = new CommandResult<>();

        try {
            CopyObjectResult copyObjectResult = jesssOptions.getAmazonS3().copyObject(copyObjectRequest);
            commandResult.setResultValue(copyObjectResult);
            commandResult.setResultStatus(ResultStatus.Success);

            displayMessage(String.format("CopyObjectResult:\tETag=%s\tExpirationTime=%s\tVersionID=%s\tLastModified=%s%n",
                    copyObjectResult.getETag(),
                    copyObjectResult.getExpirationTime(),
                    copyObjectResult.getVersionId(),
                    copyObjectResult.getLastModifiedDate()));

        } catch (AmazonClientException e) {
            displayMessage("Failed to copy object.");
            commandResult.setResultStatus(ResultStatus.Error);
            commandResult.setStatusMessage("Failed to copy object.");
        }

        return commandResult;
    }

    private void setOptions() {
        options = new Options();
        options.addOption("sbn", "sourceBucketName", true, "Source bucket name");
        options.addOption("sk", "sourceKey", true, "Source key");
        options.addOption("tbn", "targetBucketName", true, "Target bucket name");
        options.addOption("tk", "targetKey", true, "Target key");
    }

    private void parseArgs(String[] args) throws Exception {
        if (args == null || args.length == 0) {
            printUsage();
        }

        try {
            CommandLineParser parser = new ExtendedGnuParser(true);
            CommandLine cmd = parser.parse(options, args);

            if (cmd.hasOption("sbn")) {
                sourceBucketName = cmd.getOptionValue("sbn");
            } else {
                throw new MissingArgumentException("Missing source bucket name parameter.");
            }

            if (cmd.hasOption("sk")) {
                sourceKey = cmd.getOptionValue("sk");
            } else {
                throw new MissingArgumentException("Missing source key parameter.");
            }

            if (cmd.hasOption("tbn")) {
                targetBucketName = cmd.getOptionValue("tbn");
            } else {
                throw new MissingArgumentException("Missing target bucket name parameter.");
            }

            if (cmd.hasOption("tk")) {
                targetKey = cmd.getOptionValue("tk");
            } else {
                throw new MissingArgumentException("Missing target key parameter.");
            }
        } catch (Exception e) {
            printUsage();
            throw e;
        }
    }

    private void printUsage() {
        System.out.println("Usage:");
        System.out.println("jesss.jesss -cn copyObject -sbn <source bucket> -sk <source key> -tbn <target bucket name> -tk <target key>");
    }
}
